/* 
 * File:   TigerSuperState.cpp
 * Author: Hadrien
 * 
 * Created on 11 juillet 2012, 17:58
 */

#include "TigerSuperState.h"

TigerSuperState::~TigerSuperState() {
}
TigerSuperState::TigerSuperState(const TigerSuperState& s2) {
    m_state = s2.m_state;
    //Array initialization to zero
    for (int s_index = 0; s_index < state_t::size; s_index++) {
        for (int z_index = 0; z_index < obs_t::size; z_index++) {
            m_countObservations[s_index][z_index] = s2.m_countObservations[s_index][z_index];
        }
    }
}

TigerSuperState::TigerSuperState() {
    m_state.setValue(TigerState::tiger_left);
    //Array initialization to zero
    for (int s_index = 0; s_index < state_t::size; s_index++) {
        for (int z_index = 0; z_index < obs_t::size; z_index++) {
            m_countObservations[s_index][z_index] = 0;
        }
    }
}

TigerSuperState::TigerSuperState(const state_t& state, int Ll, int Lr, int Rl, int Rr) {
    m_state = state;
    m_countObservations[state_t::tiger_left][obs_t::hear_left] = Ll;
    m_countObservations[state_t::tiger_left][obs_t::hear_right] = Lr;
    m_countObservations[state_t::tiger_right][obs_t::hear_left] = Rl;
    m_countObservations[state_t::tiger_right][obs_t::hear_right] = Rr;
}

TigerSuperState::TigerSuperState(const state_t& state) {
    m_state = state;
    //Array initialization to zero
    for (int s_index = 0; s_index < state_t::size; s_index++) {
        for (int z_index = 0; z_index < obs_t::size; z_index++) {
            m_countObservations[s_index][z_index] = 0;
        }
    }
}

//Overload comparison to be used in a belief

bool TigerSuperState::operator == (const TigerSuperState &s2) const {
    bool b1 = (m_state.index() == s2.m_state.index());
    
    bool b3 = true;
    
    for (int s_index = 0; s_index < state_t::size; s_index++) {
        for (int z_index = 0; z_index < obs_t::size; z_index++) {
            if (m_countObservations[s_index][z_index] < s2.m_countObservations[s_index][z_index]) {
                b3 = (b3 && s2.m_countObservations[s_index][z_index] < m_countObservations[s_index][z_index]); 
                
            }
            
        }
    }
    
    return (b1 && b3);

}

bool TigerSuperState::operator < (const TigerSuperState &s2) const {
    if (m_state.index() < s2.m_state.index()) {
        return true;
    } else if (s2.m_state.index() < m_state.index()) {
        return false;
    } else {
        for (int s_index = 0; s_index < state_t::size; s_index++) {
            for (int z_index = 0; z_index < obs_t::size; z_index++) {
                if (m_countObservations[s_index][z_index] < s2.m_countObservations[s_index][z_index]) {
                    return true;
                } else if (s2.m_countObservations[s_index][z_index] < m_countObservations[s_index][z_index]) {
                    return false;
                }
            }
        }
        return false;
    }
}

TigerSuperState::state_t TigerSuperState::getState() const {
    return m_state;
}

TigerSuperState TigerSuperState::update(int a, int ss, int z) const {
    TigerSuperState newSuperState(*this);
    state_t newSS(ss);
    newSuperState.m_state = newSS;
    if (a == action_t::listen)
        newSuperState.m_countObservations[ss][z]++;
    return newSuperState;
}

double TigerSuperState::getT(int s, int a, int ss) const {
    if (a == action_t::listen) {
        if (s == ss)
            return 1;
        else
            return 0;
    } else {
        return 0.5;
    }
}

double TigerSuperState::getO(int s, int a, int z) const {
    if (a == action_t::listen) {
        double r = 0;
        for (int i = 0; i < obs_t::size; i++) {
            r += m_countObservations[s][i];
        }
        r = m_countObservations[s][z] / r;
        return r;
    } else
        return 0.5;
}

std::ostream& operator<< (std::ostream &out, const TigerSuperState &s)
{
    // Since operator<< is a friend of the Point class, we can access
    // Point's members directly.
    out << "(" << s.m_state.index() << ", " <<
        s.m_countObservations[0][0] << ", " <<
        s.m_countObservations[0][1] << ", " <<
        s.m_countObservations[1][0] << ", " <<
        s.m_countObservations[1][1] << ")";
    return out;
}
